perm filename IMPSER.FAI[IP,NET] blob
sn#702327 filedate 1983-03-14 generic text, type C, neo UTF8
COMMENT ⊗ VALID 00026 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00004 00002 ARPADR S W M U F R T1 T2 T3 T4 P1 P2 P3 P4 ful.wd hlf.wd net.wd net.by msk.hw wd2byt byt2wd oct2by BY2BIT
C00007 00003 SETAC SETT10 SAVAC POPPJ1 POPPOJ TCPCAL
C00010 00004 GET4WD GIV4WD
C00012 00005 INTCOM UILLBS IDERR
C00013 00006 IMPDSP
C00014 00007 IMPSET IMPRET IMPRE1 DDBGET DDBGE1 DDBDEA DDBREL
C00017 00008 IMSINI IMPINI NQUIET IMPIRN
C00021 00009 MTAPE IMPLUZ UUODSP MXUUO
C00025 00010 CONECT NONIP CONNEW IPADR SUP1P2
C00029 00011 LISTEN SETST PUTSTB STATUS
C00031 00012 TERMIN TERMI1 SWAIT SWAIT1
C00033 00013 DUMP WAKEMT QRUN INPSKP SNDINT
C00035 00014 NEWINI NEWLOS KILIMP
C00037 00015 TSINT TSETAL TGETAL TGETFS TGETF1 UGETAL USETTM UGETTM
C00041 00016 GENSYM SNDRST SNDWDN UNWEDG
C00043 00017 IMPRLS IMPRL1 IMPRL3 IMPRL4 RLDI RLDI1
C00045 00018 BUFO DMPO
C00047 00019 NEWOX OUT01 OUT02 OUT025 OUT05 OUT051 OUT052 OUT07 OUT09 OUT06 OUT10 OUT102
C00053 00020 BUFI UUXIT ENDCHK DMPI DMPIT
C00056 00021 INPT INPT01 INPT11 INPT12 INPT02 INPT17 INPT18 INPT19 INPT21 INPT09 INP09A INPT13 INPT14
C00071 00022 CLSO CLSI
C00073 00023 IMPW60 IMPWAT CLRAC1 STTIO1
C00077 00024 DIE
C00079 00025 UUOOOK UUOOK1 ISETEB UUOIOK
C00080 00026 >IFN IMPNUM
C00081 ENDMK
C⊗;
;ARPADR S W M U F R T1 T2 T3 T4 P1 P2 P3 P4 ful.wd hlf.wd net.wd net.by msk.hw wd2byt byt2wd oct2by BY2BIT
SUBTTL IMP UUO Routines
;JAM September '71
;MRC May '78 for extended leaders
;JJW March '83 for IP/TCP
IFN IMPNUM,<
BEGIN IMPUUO
HISYS
ARPADR←←12 ;Network number for ARPAnet
;Tops-10 AC definitions
S←←0 ;Same as WAITS IOS
W←←1
M←←2
;P←←3 ;Same as WAITS P
;J←←4 ;Same as WAITS J
U←←5
F←←6 ;Same as WAITS DDB
R←←7
T1←←10
T2←←T1+1
T3←←T2+1
T4←←T3+1
P1←←14
P2←←P1+1
P3←←P2+1
P4←←P3+1
;From NETDEF.MAC:
;constants desirable for their neumonic [sic - JJW] meaning
ful.wd==↑d36 ; the number of bits in a dec-10 word
hlf.wd==↑d18 ; the number of bits in a half word
net.wd==↑d32 ; the number of bits in a net word
net.by==↑d8 ; the number of bits in a net byte
msk.hw==mask.(<↑d16>,<↑d35>) ; mask for complementing checksum half word.
wd2byt==2 ; how to shift from words to bytes
byt2wd==-wd2byt ; how to shift from bytes to words
oct2by==↑d3 ; how to shift from an octet of bytes into bytes.
;Some more
BY2BIT←←3 ;How to shift from bytes to bits
;SETAC SETT10 SAVAC POPPJ1 POPPOJ TCPCAL
;Routines to change AC conventions back and forth from WAITS to TOPS10 at UUO
;level. We assume that P and J will be defined the same in both systems
;(because they have the same name). The TOPS10 code at IMPUUO (in TCPSER)
;sets the right half of M to the address of the argument block. For functions
;that we do by MTAPE, register UUO already has that in it so things work right.
;At UUO level, ACs normally start out in WAITS mode. We do a PUSHACS to save
;them and then SETT10 to set the values in registers expected by TOPS-10 code.
;If other ACs have to be set up, individual calls to SETAC may be used.
DEFINE SETAC(AC,SVAC)<
IFN AC-SVAC,<
MOVE AC,SVAC-17(P)
>>
DEFINE SETT10<
SETAC(S,IOS)
SETAC(F,DDB)
SETAC(M,UUO)
>
;To get back into WAITS mode, first use SAVAC to save any values that may have
;changed. Then POPACS to get back ACs that were pushed.
DEFINE SAVAC(SVAC,AC)<
MOVEM AC,SVAC-17(P)
>
POPPJ1: POPACS ;Restore and skip return
AOSA(P)
POPPOJ: POPACS ;Restore and normal return
POPJ P,
;Macro to call an IMPUUO handler in TCPSER. Assume TOPS-10 ACs have been set up.
;Sets up left half of P4 and turns scanner off and on again if needed. Skip
;returns are ignored - error code in status bits will have been set.
DEFINE TCPCAL ' (DD)<
MOVE P4,[.W'DD]
TLNN P4,UU.INT
OFFSCN
PUSHJ P,(P4)
JFCL
TLNN P4,UU.INT
ONSCN
>
;GET4WD GIV4WD
;Storage management - WAITS simulation of TOPS-10 code.
;Here to allocate a multiple of 4 words.
;
;Calling:
; MOVEI T2,<# of 4-word blocks>
; PUSHJ P,GET4WD
; <not available - largest possible in T2>
; <OK - address of block is in T1>
;
;NOTE: Not implemented putting address of largest possible block in T2. Calls
;to here from NETSUB and TCPSER never use this feature.
GET4WD: PUSHACS ;Save TOPS-10 ACs
SETAC(AC3,T2) ;Set up the right AC
LSH AC3,2 ;Number of words
PUSHJ P,FSGET
JRST POPPOJ
SAVAV(T1,AC1) ;Address of block
JRST POPPJ1
;Here to release blocks allocated by GET4WD.
;
;Calling:
; MOVEI T1,<# of 4-word blocks>
; MOVEI T2,<starting address>
; PUSHJ P,GIV4WD
; <return here always>
GIV4WD: PUSHACS ;Save TOPS-10 ACs
SETAC(AC1,T2)
PUSHJ P,FSGIVE
POPACS
POPJ P,
;INTCOM UILLBS IDERR
;Routine to plant an interrupt request. Called from TOPS-10 AC's with F
;set up and interrupt bit in T1.
INTCOM: LDB J,PJOBN
JUMPE J,CPOPJ ;Make sure it's a real job
TDNN T1,JBTIEN(J)
POPJ P,
IORM T1,JBTIRQ(J)
TDNE T1,JBTMSK(J) ; ANY BIT MASKED ON?
SETOM INTREQ ; YES, RUN INTERRUPTS
POPJ P,
;Here to return error codes to user.
UILLBS: SKIPA TAC,[ILB]
IDERR: MOVEI TAC,IDD
XCTR XW,[MOVEM TAC,STLOC(UUO)]
POPJ P,
;IMPDSP
; UUO DISPATCH TABLE
POPJ P, ; Don't flush DDB - let TCPSER code do that
JRST IMPSET ; DDB MAKE
JRST IMSINI ; SYSTEM INITIALIZATION
POPJ P, ; NO HUNG TIMEOUT
↑IMPDSP:JRST IMPRLS ; RELEASE
JRST CLSO ; CLOSE OUTPUT
JRST BUFO ; BUFFERED OUTPUT
JRST BUFI ; BUFFERED INPUT
JRST CPOPJ1 ; ENTER
JRST CPOPJ1 ; LOOKUP
JRST DMPO ; DUMP MODE OUTPUT
JRST DMPI ; DUMP MODE INPUT
POPJ P, ; USETO
POPJ P, ; USETI
POPJ P, ; UGETF
JRST CPOPJ1 ; RENAME
JRST CLSI ; CLOSE INPUT
POPJ P, ; UTPCLR
JRST MTAPE ; MTAPE
;IMPSET IMPRET IMPRE1 DDBGET DDBGE1 DDBDEA DDBREL
; ROUTINES TO MAKE AND RELEASE IMP DEVICE DATA BLOCKS
↑IMPSET:MOVEI AC3,IMPDLN ; MAKE A BLOCK
PUSHJ P,FSGET
JRST [ ADJSP P,-3
JRST DLYCM1]
HRRI DDB,DDBSKW(AC1) ; POINT DDB AT DEVICE NAME
HRLI AC1,IMPDDB-DDBSKW ; COPY DDB FROM PROTOTYPE
BLT AC1,IMPDLS(DDB)
MOVEI AC1,DEVIOS(DDB) ; SET UP SPT
MOVEM AC1,DEVSPT(DDB)
HRLM DDB,IMPDDB+DEVSER ; LINK IN DDB CHAIN
POPJ P,
↑IMPRET:SETZB IOS,DEVIOS(DDB) ; FLUSH IOS
MOVEI AC1,IMPDDB ; FIND DDB
IMPRE1: MOVE TAC1,AC1
HLRZ AC1,DEVSER(TAC1)
JUMPE AC1,CPOPJ ; DDB NOT FOUND? (SHOULDN'T HAPPEN BUT IT DOES)
CAIE AC1,(DDB)
JRST IMPRE1
MOVE DDB,DEVSER(AC1) ; DELETE DDB FROM CHAIN
HLLM DDB,DEVSER(TAC1)
SUBI AC1,DDBSKW ; RETURN TO FS
JRST FSGIVE
;The following replaces DDBGET in NETSUB. May be called at interrupt level.
;Never waits. Skip returns if successful.
DDBGET: PUSHACS ;Don't damage AC's TOPS-10 may use
MOVEI AC3,IMPDLN ; MAKE A BLOCK
PUSHJ P,FSGET
JRST DDBGE1
AOS -20(P) ; Indicate our success
HRRI DDB,DDBSKW(AC1) ; POINT DDB AT DEVICE NAME
HRLI AC1,IMPDDB-DDBSKW ; COPY DDB FROM PROTOTYPE
BLT AC1,IMPDLS(DDB)
MOVEI AC1,DEVIOS(DDB) ; SET UP SPT
MOVEM AC1,DEVSPT(DDB)
HRLM DDB,IMPDDB+DEVSER ; LINK IN DDB CHAIN
SAVAC(F,DDB) ;Make POPACS pop DDB into F
DDBGE1: POPACS
POPJ P,
;Here from TOPS-10 code to release a DDB.
DDBDEA:
DDBREL: PUSHACS ;Save away TOPS-10 ACs
SETAC(DDB,F)
PUSHJ P,IMPRET
POPACS ;Get ACs back
POPJ P,
;IMSINI IMPINI NQUIET IMPIRN
; SYSTEM INITIALIZE ROUTINE
IMSINI: SETOM IMPINF ; SYSTEM INITIALIZATION
SETZM OURHST ; don't know our host/imp number yet
SETZM DIFHST ; and it hasn't changed yet either
PUSHACS ;Get into TOPS-10 mode
SETT10
PUSHJ P,INI↑ ;(in IMPSER.MAC)
POPACS ;back to WAITS mode
POPJ P,
; NCP RE-INITIALIZE ROUTINE
IMPINI: SETZM IMPST ; CLEAR DATA AREA
MOVE AC1,[IMPST,,IMPST+1]
BLT AC1,IMPEND-1
NQUIET←←5 ;NUMBER OF MINUTES OF SUPPRESSION OF IMP ERROR MESSAGES
MOVEI AC1,NQUIET ; NUMBER OF MINUTES OF SILENCE FOR CTY
MOVEM AC1,IQUIET ; SUPPRESS ERROR MESSAGES FOR A WHILE
SKIPE IMPDIE ; DO WE KEEP THE IMP DOWN TODAY?
JRST [ SETOM IMPDEAD ; YES
POPJ P,]
MOVEI AC1,P1PID
MOVEM AC1,IMPPID
MOVEI AC1,IBEGIN ; INITIALIZE THE I-LEVEL DISPATCH ADDRESSES
MOVEM AC1,IMPIDSP
HRLOI AC1,377777 ; SET OUTPUT COUNT-DOWN TO RANDOM LARGE NUMBER
MOVEM AC1,IMPOCT
MOVEI AC1,DONOP
MOVEM AC1,IMPODSP ; start outputting no-ops to IMP interface
MOVEI AC1,10 ; GIVE A LITTLE WHILE FOR THE IMP RELAY TO COOL OFF
MOVEM AC1,HCLCNT
MOVEI AC1,IMPSPL ; PICK UP A BUNCH OF SPARE FREE STORAGE BLOCKS
MOVEM AC1,IMPSPN
PUSHJ P,IMPREP
MOVE AC1,[-INTPLN,,IMPIPL-1]
MOVEM AC1,IMPIPD
MOVE AC1,[-INTPLN,,IMPOPL-1]
MOVEM AC1,IMPOPD
MOVEI AC1,5*JIFSEC
MOVEM AC1,UPWCNT ; RESET INTERFACE RESET CLOCK
IFE FTF2,<
CONO IMP,ODPIEN ; Clear PIA for output (why? it's set just below!)
CONO IMP,STRIN!CLRWT!IDPIEN!IEPIEN!IMPCHN ;Set PIAs for input
>;IFE FTF2
IFN FTF2,<
CONO IMP,IDPIEN!IEPIEN!IMPCHN!<IMPCHN⊗8> ;Set PIAs for input
>;IFN FTF2
MOVEI AC3,4 ; SEND THE IMP SOME NOPS
MOVEM AC3,NOPCNT
SETOM IMPOACT
MOVEI AC3,MAXCNT
MOVEM AC3,IMPOCT
CONO PI,IMPOFF
IFN FTF2,<
CONO IMP,ODPIEN!<IMPCHN⊗4> ; set output PIA
>;IFN FTF2
IFE FTF2,<
CONO IMP,STROUT!ODPIEN!IMPCHN!O32 ; 32 BIT output MODE, DAMNIT!
;The following DATAO must occur here, not at interrupt level, for system
;initialization to be able to get the IMP interface going after a power up on
;the IMP interface. For simplicity, we'll do the DATAO here for all WAITS.
>;IFE FTF2
DATAO IMP,[BYTE (4)0 (4)17 (16)0 (8)4] ; NOP
CONO PI,IMPON
IMPIRN: MOVEI TAC,['IMPRST' ↔ ' 1 2' ↔ UPGPRV,,0]
PUSHJ P,FIREUP ; RUN MAGIC WORLD RESETTER
CAIA
POPJ P,
MOVSI TAC,IMPIRN
CONO PI,PIOFF
IDPB TAC,CLKQ
CONO PI,PION
POPJ P,
;MTAPE IMPLUZ UUODSP MXUUO
; MTAPE DISPATCH
MTAPE: XCTR XR,[HRRZ TAC,(UUO)] ; GET FUNCTION CODE
CAIL TAC,MXUUO ; FUNCTION IN BOUNDS?
JRST UUOERR ; ILLEGAL FUNCTION
SKIPG STATE(DDB) ; is it a closed DDB?
PUSHJ P,CLRIMP↑ ; yes. CLEAR THE DDB (in NETSUB.MAC)
SKIPL TAC1,UUODSP(TAC) ; GET DISPATCH ADDRESS
SKIPE IMPUP↑ ; FUNCTION REQUIRES LIVING IMP
JRST (TAC1) ; ALIVE OR FOR A DEAD IMP
TLNE TAC1,200000 ; DOES THIS MTAPE EXPECT STATUS BITS?
JRST IDERR ; YES, RETURN IDD ERROR
TLNE TAC1,100000 ; FUNCTION NO-OP WHEN IMP DOWN?
POPJ P,
IMPLUZ: JSP TAC,UUOMES ; NOPE, BLAST USER'S JOB
ASCIZ/IMP dead, UUO/
; IMP MTAPE UUO DISPATCH TABLE. LH BITS ARE:
; 400000 → THIS MTAPE ALWAYS WINS WHETHER OR NOT IMP IS DEAD
; 200000 → THIS MTAPE RETURNS STATUS BITS IN ARG BLOCK+STLOC, SO SET IDD IF IMP DEAD
; 100000 → THIS MTAPE IS A NO-OP IF THE IMP IS DEAD
; IF NONE OF THESE BITS ARE SET USER GETS AN "IMP DEAD" MESSAGE.
UUODSP: 200000,,CONECT ; 0 ESTABLISH CONNECTION
200000,,LISTEN ; 1 LISTEN ON A SOCKET
200000,,STATUS ; 2 GET STATUS BITS
200000,,TERMIN ; 3 TERMINATE CONNECTION (LIKE CLOSE UUO)
200000,,SWAIT ; 4 WAIT FOR CONNECTION
400000,,DUMP ; 5 GET POINTERS TO SYSTEM SYMBOLS
WAKEMT ; 6 WAKE UP USER PROCESS FROM I-LEVEL
200000,,SETST ; 7 GET STATUS BLOCK (USED AFTER LISTEN)
INPSKP ; 10 SKIP IF IMP INPUT
200000,,SNDINT ; 11 SEND INR/INS
400000,,NEWINI ; 12 TURN ON IMP
100000,,KILIMP ; 13 TURN OFF IMP
TSINT ; 14 TEST AND CLEAR INTERRUPT STATUS
100000,,TSETAL ; 15 SET ALLOCATION
100000,,TGETAL ; 16 GET ALLOCATION
100000,,USETTM ; 17 SET TIMEOUTS
100000,,UGETTM ; 20 GET TIMEOUTS
100000,,GENSYM ; 21 GENSYM A SOCKET FOR ICP
SNDRST ; 22 SEND A RESET
100000,,SNDWDN ; 23 SEND HOST DOWN STATUS MESSAGE
UNWEDG ; 24 ATTEMPT TO UNWEDGE AN IMP CONNECTION
MXUUO←←.-UUODSP
;CONECT NONIP CONNEW IPADR SUP1P2
;Here we try to distinguish between NCP host/IMP numbers and IP addresses.
;If an IP address is given, it must include a valid net number (ARPADR).
CONECT: XCTR XR,[MOVE AC2,HLOC(UUO)] ;Get host number from user
TLNE AC2,740000 ;Left 4 bits 0?
JRST NONIP ;No. Can't be an IP address.
LDB AC3,[POINT 8,AC2,11] ;Network number in IP format
CAIN AC3,ARPADR ;ARPAnet?
JRST IPADR ;Yes. Wouldn't be legal in NCP format.
CAIE AC3,ARPADR⊗3 ;ARPAnet in NCP format?
JUMPN AC3,UUOERR ;No. If not 0, punt.
NONIP: LDB AC3,[POINT 8,AC2,8] ;Network number in NCP format
SKIPN AC3
MOVEI AC3,ARPADR ;Default to ARPAnet
CAIE AC3,ARPADR ;Check network for legality
JRST UUOERR ;Unknown network
TDNE AC2,[400600,,000400] ; LEGAL NUMBER?
JRST UUOERR ; BLAST THIS LOSER OUT OF THE WATER!
TDNE AC2,[000177,,777000] ; OLD OR NEW STYLE NUMBER?
JRST CONNEW
DPB AC2,[POINT 6,AC2,20] ; STORE IMP NUMBER IN NEW FORMAT
LSH AC2,-6 ; RIGHT-ALIGN HOST NUMBER
;Host/IMP number is now in "new" NCP form in AC2, net number in AC3.
;Form IP address in AC1.
CONNEW: DPB AC3,[POINT 11,AC1,11] ;Net number in IP address
LDB AC3,[POINT 8,AC2,35]
DPB AC3,[POINT 8,AC1,19] ;Host number
LDB AC3,[POINT 16,AC2,26]
DPB AC3,[POINT 16,AC1,35] ;IMP number
XCTR XW,[MOVEM AC1,HLOC(UUO)] ;Return it to the user
;Check byte size. 0 or =8 is accepted, =8 always returned.
IPADR: XCTR XR,[SKIPN DAT,BSLOC(UUO)]
MOVEI DAT,=8 ;Default 0 to =8
CAIE DAT,=8
JRST UILLBS ;Bad byte size
XCTR XW,[MOVEM DAT,BSLOC(UUO)]
;Call TCPSER code to make the connection.
PUSHACS ;Get into TOPS-10 mode
SETT10
PUSHJ P,SUP1P2
TCPCAL(CONN)
;TCPSER will have stored generated port number, if any, in LSLOC(UUO).
POPACS ;Back to WAITS mode
JRST PUTSTB ;Give user status bits and return
;Here to set up P1 and P2 for TOPS10 code, after doing SETT10. P1 gets flags
;in left half; P2 gets TOPS10 version of local port number in MTAPE block,
;to allow generation of new port numbers.
SUP1P2: SETZ P1, ;All flags off initially
XCTR XR,[SKIPN WFLOC(M)] ;See if we should wait
TLO P1,(IF.NWT) ;No wait.
MOVSI T1,UPGPRV ;Is UPG enabled?
TDNE T1,JBTPRV(J)
TLO P1,(IF.PRV) ;Yes.
XCTR XR,[MOVE P2,LSLOC(M)] ;Get local port supplied by user
CAME P2,[-1] ;Is he asking for a gensymmed port?
TLOA P1,(IF.ALS) ;No, absolute.
SETZ P2, ;Yes. Ask for 0 in lower 3 bits.
POPJ P,
;LISTEN SETST PUTSTB STATUS
LISTEN: XCTR XRW,[MOVES HLOC(UUO)] ;Address check
XCTR XW,[SETOM FSLOC(UUO)] ;Show no connection yet
PUSHACS ;Get into TOPS-10 mode
SETT10
PUSHJ P,SUP1P2 ;Set wait flag and others
TCPCAL(REQU) ;This stores info in the DDB
POPACS ;Back to WAITS mode
SETST: MOVE AC2,LCLPRT(DDB) ;Store local port if we got one
XCTR XW,[MOVEM AC2,LSLOC(UUO)]
MOVEI AC2,=8 ;Return fixed byte size
XCTR XW,[MOVEM AC2,BSLOC(UUO)]
MOVE AC2,RMTPRT(DDB) ;Remote port will be -1 if none yet
XCTR XW,[MOVEM AC2,FSLOC(UUO)]
MOVE AC2,RMTADR(DDB) ;Store remote host
XCTR XW,[MOVEM AC2,HLOC(UUO)]
; JRST PUTSTB ;Give him status bits and return
;Here to store status in usual return location.
PUTSTB: MOVE AC2,STB(DDB) ;Current status
MOVE AC3,STATE(DDB) ;Get TCP state
DPB AC3,[POINT 4,AC2,9] ;Add to status word
XCTR XW,[MOVEM AC2,1(UUO)] ;Give it to user
POPJ P,
;STATUS call returns same values in both words.
STATUS: PUSHJ P,PUTSTB
XCTR XW,[MOVEM AC2,2(UUO)]
POPJ P,
;TERMIN TERMI1 SWAIT SWAIT1
; TERMINATE CONNECTION
TERMIN: XCTR XR,[SKIPE AC2,LSLOC(UUO)] ;Get desired port
CAMN AC2,LCLPRT(DDB) ;Is it ours?
JRST TERMI1
JSP TAC,UUOMES
ASCIZ/Illegal port in terminate, UUO/
TERMI1: PUSHACS ;Get into TOPS-10 mode
SETT10
TCPCAL(CLOS)
POPACS ;Back to WAITS mode
JRST PUTSTB ;Give him status bits and return
; ROUTINE TO WAIT FOR CONNECTION
SWAIT: XCTR XR,[SKIPE AC2,LSLOC(UUO)] ;Get desired port
CAMN AC2,LCLPRT(DDB) ;Is it ours?
JRST SWAIT1
JSP TAC,UUOMES
ASCIZ/Illegal port in wait, UUO/
SWAIT1: PUSHACS ;Get into TOPS-10 mode
SETT10
MOVEI T1,S%LIST ;Waiting to get out of listen state
OFFSCN ;ESTBWT (in TCPSER.MAC) expects this
PUSHJ P,ESTBWT↑ ;Wait to get into established or better.
JFCL ;Error return nothing special
ONSCN
POPACS ;Back to WAITS mode
JRST PUTSTB
;DUMP WAKEMT QRUN INPSKP SNDINT
;DUMP not implemented yet for IP/TCP.
DUMP: JRST UUOERR
; WAKE UP MONITOR IF WAITING FOR IMP. SETS TMO IN IOS TO INDICATE ERROR CONDITION
;(Unchanged from old IMPSER, so PUPSER can still call this.)
↑WAKEMT:SKIPN INTACT
POPJ P,
MOVE IOS,DEVIOS(DDB)
TLNN IOS,ANYW
POPJ P,
TRO IOS,TMO
MOVEM IOS,DEVIOS(DDB)
; JRST QRUN
; ROUTINE TO REQUEUE SOMEONE INTO THE RUN QUEUE
; ENTER WITH DDB CONTAINING THE DDB
QRUN: LDB J,PJOBN
SKIPL IMPTIM(DDB) ; MAKE SURE TIMEOUT IS CLEARED
SOS TIMWAIT ; NOTE ONE LESS WAITOR
SETOM IMPTIM(DDB)
JRST STTIOD ; NOW RUN HER
; ROUTINE TO SKIP IF THERE IS ANY INPUT PRESENT
INPSKP: SKIPE IBFTHS(DDB) ;Any input?
AOS (P) ;Yes.
POPJ P,
;SNDINT not implemented for IP/TCP. No interrupt is sent, but status bits are
;returned.
SNDINT: JRST PUTSTB
;NEWINI NEWLOS KILIMP
; REINITIALIZE THE IMP SYSTEM, BRING UP THE IMP
NEWINI: MOVSI AC2,UPGPRV
SKIPE IMPDIE ; CLOCK LEVEL DOES IT IF IMPDIE=0
TDNN AC2,JBTPRV(J)
JRST UUOERR
SKIPE IMPUP↑
JRST NEWLOS
PUSHJ P,DISUSR
SIXBIT/NET/
PUSHJ P,DISMES
ASCIZ/IMP on, user=/
MOVE TAC1,PRJPRG(J)
PUSHJ P,DISSIX
PUSHJ P,DISMES
ASCIZ/, job=/
PUSHJ P,DISJOB
PUSHJ P,DISCRLF
SETZM IMPDIE
SETOM IMPUP↑ ;JJW - for IP/TCP code
JRST IMPINI
NEWLOS: PUSHJ P,TTYERR
JSP TAC,UUOMES
ASCIZ/IMP already alive, UUO/
; BRING THE IMP DOWN
KILIMP: MOVSI AC2,UPGPRV
TDNN AC2,JBTPRV(J)
JRST UUOERR
PUSHJ P,DISUSR
SIXBIT/NET/
PUSHJ P,DISMES
ASCIZ/IMP off, user=/
MOVE TAC1,PRJPRG(J)
PUSHJ P,DISSIX
PUSHJ P,DISMES
ASCIZ/, job=/
PUSHJ P,DISJOB
PUSHJ P,DISCRLF
SETOM IMPDIE ; KEEP IT DOWN!
MOVEI TAC,1 ;JJW - for IP/TCP
MOVEM TAC,IMPUP↑
POPJ P,
;JJW - previously there was the following instruction:
; JRST IMPDD0
;which went to some code in IMPSER. It appears that setting IMPUP to 1 may
;be sufficient since the clock-level code in IMPSER.MAC takes some action based
;on this (like sending a "going down" message).
;TSINT TSETAL TGETAL TGETFS TGETF1 UGETAL USETTM UGETTM
; TEST AND CLEAR INTERRUPT BITS - SET SYSTEM DEFAULT TIMEOUTS
; RETURNS FLAG FOR SEND SIDE IN 1(UUO), RECEIVE SIDE IN 2(UUO)
;JJW - now always returns 0.
TSINT: ANDI DDB,-1
XCTR XW,[SETZM 1(UUO)]
XCTR XW,[SETZM 2(UUO)]
POPJ P,
;SET ALLOCATION is not yet supported by the code in TCPSER. Until it is,
;this MTAPE will be a no-op.
TSETAL: POPJ P,
;GET ALLOCATIONS - This code only sets the bit allocation fields, and
;always to a multiple of 8 bits. The message allocation fields are zeroed.
TGETAL: MOVE TAC,RCVWND(DDB)
LSH TAC,BY2BIT ;convert bytes to bits
XCTR XW,[MOVEM TAC,1(UUO)]
XCTR XW,[SETZM 2(UUO)]
;JJW - I'm not sure how to compute the value for 3(UUO)
XCTR XW,[SETZM 4(UUO)]
PUSHJ P,TGETFS
LSH TAC,BY2BIT
XCTR XW,[MOVEM TAC,5(UUO)]
XCTR XW,[SETZM 6(UUO)]
MOVE TAC,SNDWND(DDB)
LSH TAC,BY2BIT
XCTR XW,[MOVEM TAC,7(UUO)]
XCTR XW,[SETZM 10(UUO)]
POPJ P,
;Here to add up number of bytes in free storage (i.e., on input list)
;and return in TAC.
TGETFS: MOVE TAC,IBFBC(DDB) ;Bytes in current buffer
MOVE AC1,IBFTHS(DDB) ;Current buffer
TGETF1: HRRZ AC1,AC1 ;Advance to next buffer
JUMPE AC1,CPOPJ
HLRZ TAC1,AC1 ;Get byte count
ADDI TAC,(TAC1) ;Add it in
JRST TGETF1
;Following should be moved to PUPSER since IMPSER no longer uses it.
; MTAPE 14 - GIVE USER THE CURRENT ALLOCATIONS
; THIS CODE IS ALSO USED BY PUPSER
↑UGETAL:MOVE TAC,NHBA(DDB)
XCTR XW,[MOVEM TAC,1(UUO)]
MOVE TAC,NHMA(DDB)
XCTR XW,[MOVEM TAC,2(UUO)]
MOVE TAC,HBA(DDB)
XCTR XW,[MOVEM TAC,3(UUO)]
MOVE TAC,HMA(DDB)
XCTR XW,[MOVEM TAC,4(UUO)]
MOVE TAC,BIIL(DDB)
XCTR XW,[MOVEM TAC,5(UUO)]
MOVE TAC,MIIL(DDB)
XCTR XW,[MOVEM TAC,6(UUO)]
MOVE TAC,BAL(DDB)
XCTR XW,[MOVEM TAC,7(UUO)]
MOVE TAC,MAL(DDB)
XCTR XW,[MOVEM TAC,10(UUO)]
POPJ P,
; SET SYSTEM DEFAULT TIMEOUTS. PUT WORD OF 6-BIT FIELDS IN 1(UUO).
; THE FIELDS ARE IN UNITS OF 2-SECONDS. I.E., THE MAXIMUM WAIT IS 126 SECONDS
; AND THE MINIMUM WAIT IS 2 SECONDS.
; THIS CODE IS ALSO USED BY PUPSER
↑USETTM:XCTR XR,[MOVE AC1,1(UUO)]
MOVEM AC1,TIMES(DDB)
POPJ P,
; ROUTINE TO GET CURRENT TIMEOUTS
↑UGETTM:MOVE AC1,TIMES(DDB)
XCTR XW,[MOVEM AC1,1(UUO)]
POPJ P,
;GENSYM SNDRST SNDWDN UNWEDG
;Generate a local port number. This is done by calling the appropriate
;routine in TCPSER.
GENSYM: XCTR XRW,[MOVES 1(UUO)] ;Address check
PUSHACS ;Get into TOPS-10 mode
SETT10
SETZB P1,P2 ;To ask for a free socket
PUSHJ P,MAKMYS↑
XCTR XW,[MOVEM T1,1(M)] ;Store result in argument block
POPACS ;Back to WAITS mode
POPJ P,
;SEND RESET - not possible in TCP.
SNDRST: JRST UUOERR
;Send a HOST GOING DOWN message - not implemented yet in IMPSER.MAC.
SNDWDN: MOVSI AC1,UPGPRV
TDNN AC1,JBTPRV(J) ; ENABLED UPG?
JRST UUOERR
POPJ P,
;Unwedge a connection - no longer legal.
UNWEDG: JRST UUOERR
;IMPRLS IMPRL1 IMPRL3 IMPRL4 RLDI RLDI1
;JJW - needs work.
; RELEAS CODE. SEND OUT CLSS IF NOT ALREADY.
IMPRLS: SKIPL IMPTIM(DDB) ; TIME INITIALIZED?
SOS TIMWAIT ; YES, NOT ANY MORE
SETOM IMPTIM(DDB)
SKIPE AC1,INL(DDB) ; ANYTHING STILL ON INPUT LIST?
PUSHJ P,RELBLS ; YES, GIVE IT BACK
SKIPN IMPUP↑
JRST RLDI
MOVE IOS,DEVIOS(DDB)
TRNE IOS,BLOK
PUSHJ P,RFNMWT ; IF STILL DATA ON THE LINK, WAIT FOR IT
PUSHJ P,UUSIDX
JRST IMPRL3
MOVE AC1,IMPSTB-1(AC3)
TLNE AC1,RFCS
TLNE AC1,CLSS
JRST IMPRL1
PUSHJ P,USCLS
PUSHJ P,UUSIDX
JRST IMPRL3
IMPRL1: SETZM LNKDDB-1(AC3)
PUSHJ P,ZEROLK
IMPRL3: PUSHJ P,UURIDX
POPJ P,
MOVE AC1,IMPSTB-1(AC3)
TLNE AC1,RFCS
TLNE AC1,CLSS
JRST IMPRL4
PUSHJ P,URCLS
PUSHJ P,UURIDX
POPJ P,
IMPRL4: SETZM LNKDDB-1(AC3)
JRST ZEROLK ; RELEASE CONNECTION IF ALL CLSS ARE PROPERLY EXCHANGED
; WE GET HERE IF THE IMP IS DEAD
RLDI: PUSHJ P,UUSIDX ; SEE IF HE HAS A SEND SOCKET
JRST RLDI1
SETZM LNKDDB-1(AC3) ; YES, KILL IT
PUSHJ P,ZEROLK
RLDI1: PUSHJ P,UURIDX
POPJ P,
SETZM LNKDDB-1(AC3)
JRST ZEROLK
;BUFO DMPO
;BUFFERED OUTPUT, DUMP MODE OUTPUT
;JJW - because the TOPS-10 IMPSER.MAC implements only buffered mode (and even
;that in a slightly different way from WAITS), the code here is a hybrid of that
;and the old NCP code in WAITS. The same holds for input UUO code.
BUFO: PUSHJ P,UUOOOK ; IS HOST ALIVE AND ALL?
JRST UUXIT ; NO, LEAVE WITH ERROR BITS
HRRZ TAC1,DEVOAD(DDB) ; PICK UP OUT BUFFER ADDRESS
XCTR XR,[HRRZ ITEM,1(TAC1)] ; PICK UP WORD COUNT
PUSHJ P,ITMCNT ;Count number of bytes
HRRZ TAC1,DEVOAD(DDB) ;Buffer address
ADDI TAC1,2 ; MOVE POINTER TO DATA AREA
PUSHJ P,NEWOX ;Do transfer with user addr in TAC1 and byte
;count in ITEM
PUSHJ P,ADVBFE ; ADVANCE BUFFER
JRST UUXIT
JRST BUFO ; TRY FOR ANOTHER ONE
; DUMP MODE OUTPUT
DMPO: PUSHJ P,UUOOOK
JRST UUXIT
PUSHJ P,DMPCMD ;FETCH NEXT IOWD.
POPJ P, ;END OF COMMAND LIST
MOVN ITEM,TAC ;POSITIVE WC
LSH ITEM,WD2BYT ;Byte count
HRRZ TAC1,TAC1 ;TAC1←USER-RELATIVE STARTING ADDRESS
PUSH P,UUO ;SAVE POINTER TO COMMAND LIST
PUSHJ P,NEWOX ;DO TRANSFER
POP P,UUO
AOJA UUO,DMPO ;DO NEXT COMMAND
;NEWOX OUT01 OUT02 OUT025 OUT05 OUT051 OUT052 OUT07 OUT09 OUT06 OUT10 OUT102
; ROUTINE TO ACTUALLY DO THE OUTPUT
; ENTER WITH byte COUNT IN ITEM AND USER ADDRESS IN TAC1
NEWOX: JUMPE ITEM,CPOPJ ; LEAVE IF USER byte COUNT=0
HRLI TAC1,441000 ; MAKE INPUT POINTER INTO BYTE POINTER
PRINTX IMP output only reads 8-bit bytes from user core
;JJW - all output is done byte-by-byte. This doesn't add much in the way of
;inefficiency, because checksumming has to get done sometime, and OUBYTE handles
;this. (We could possibly use the code that checksums words, but for now that
;looks too hairy.) Code here is derived from OUTPT in IMPSER.MAC.
PUSHACS ;Get into TOPS-10 mode
SETT10
SETAC(P1,TAC1) ;User address of data
SETAC(P2,ITEM) ;Desired byte count
;P3 is used to keep the running checksum. P4 is the coroutine pointer.
OUT01: SKIPE OKFLAG ;ALL OK?
SKIPE STOPFL
JRST OUT09 ;NO
OUT02: PUSHJ P,TCPOCK↑ ;OPEN FOR OUTPUT? (in TCPSER.MAC)
JRST OUT102 ;NO
MOVEI P4,OUBYTE↑ ;ASSUME BYTE MODE (in IMPSER.MAC)
MOVSI S,IO
IORB S,DEVIOS(F)
JUMPLE P2,OUT051 ;Jump if no data
;TEST FOR ALLOCATION
MOVSI S,ALLCWT ;SET WAIT FLAG
IORM S,IMPIOS(F)
IORB S,DEVIOS(F)
PUSHJ P,TCPTCK↑ ; is there enough window available?
JRST OUT07 ; no window or not enough. wait.
;OUTPUT LOOP
OUT025: XCTR XR,[ILDB T1,P1] ;Get a character
OFFSCN
PUSHJ P,OTBYTE↑ ;BUFFER AND COUNT IT
JRST OUT06 ;LOSE!!!
ONSCN
SOJG P2,OUT025 ;Loop for more
SKIPG OBFBYT(F) ;DID WE BUFFER ANYTHING?
JRST OUT051 ;NO, SO DON'T SEND ANYTHING
;HERE WHEN TRANSFER TO MONITOR BUFFER STOPPED.
OUT05: SKIPG P2 ; is this the last byte in the buffer?
PUSHJ P,TCPPSH↑ ; yes. let TCP do push handling.
OFFSCN
PUSHJ P,OUTPRE↑ ; predict if we will have enough buffers
; for this message. (in IMPSER.MAC)
JRST [ ; not enough room.
ONSCN ; interrupts back on
JRST OUT10] ; indicate error
PUSHJ P,OUTBYT↑ ; send it out (in IMPSER.MAC)
ONSCN
JUMPG P2,OUT02 ;Jump if any bytes left
;Here when done a transfer.
OUT051:
MOVSI S,IOBEG
SKIPE IBFTHS(F) ;ANY INPUT DATA?
TDNN S,DEVIOS(F) ;AND STILL VIRGIN INPUT SIDE?
JRST OUT052 ;NO
MOVEI S,IODATA ;YES
IORB S,DEVIOS(F) ;SET DATA BIT
OUT052: PUSHJ P,IMPWK1↑ ;(in IMPSER.MAC)
SAVAC(IOS,S)
POPACS ;Back to WAITS mode
POPJ P,
;HERE TO WAIT
OUT07: OFFSCN ; interlock so IMPW60 doesn't damage some
; one else's lock. (lock the lock)
PUSHJ P,IMPW60↑ ;WAIT A MINUTE
JRST OUT02 ;TRY AGAIN
;HERE IF IMP OFF LINE OR SOME SUCH
OUT09: SAVAC(IOS,S)
POPACS ;Back to WAITS mode
PUSHJ P,HNGSTP ;TYPE USER MESSAGE AND STOP
JRST OUT01 ;TRY AGAIN IF HE CONTINUES
;HERE IF FAILED TO PACK BYTE INTO BUFFER. T2 CONTAINS CERROR FLAG
OUT06: ONSCN ; allow interrupts again
LDB T1,[POINT 6,P1,11] ;GET BYTE SIZE
ROT T1,-6
ADD P1,T1 ;BACK UP BYTE POINTER
JUMPN T2,OUT05 ;IF NON-ZERO, MESSAGE SIZE OR ALLOCATION
;HERE IF NO BUFFERS LEFT
OUT10: MOVEI S,IODERR ;DEVICE ERROR
SKIPA
OUT102: MOVEI S,IOIMPM ;IMPROPER MODE
IORB S,DEVIOS(F)
OFFSCN
SKIPE T1,OBFFST(F) ;IS THERE A STREAM?
PUSHJ P,RELBUF↑ ;YES, CLEAR IT (in NETSUB.MAC)
SETZM OBFFST(F) ; clear pointer to stream.
ONSCN
JRST OUT051
;BUFI UUXIT ENDCHK DMPI DMPIT
; IMP INPUT UUOS - BUFFERED MODE AND DUMP MODE
BUFI: HRRZ TAC1,DEVIAD(DDB) ; ADDRESS OF USER'S BUFFER
XCTR XR,[HLRZ TAC,(TAC1)]; TAC←BUFFER SIZE
ANDCMI TAC,400000 ; IGNORE BUFFER USE BIT
MOVEI DSER,(TAC1)
ADDI DSER,(TAC) ; ADDRESS OF LAST DATA WORD IN BUFFER
XCTR XRW,[MOVES (DSER)] ; ADDRESS CHECK
SUBI TAC,1 ; REDUCE BUFFER WC TO SKIP 1 OVERHEAD WORD
ADDI TAC1,2 ; ADVANCE TO POINT TO FIRST DATA WORD.
PUSHJ P,INPT ; DO THE INPUT.
JRST ENDCHK ; ERROR OR EOF
HRRZ AC2,DEVIAD(DDB) ; PICK UP BUFFER ADDRESS
XCTR XW,[MOVEM DAT,1(AC2)] ; SET WORD COUNT IN BUFFER
PUSHJ P,ADVBFF ; ADVANCE THE BUFFER
CAI
UUXIT: MOVE IOS,DEVIOS(DDB) ; UUOCON EXPECTS THIS
POPJ P,
ENDCHK: TLZE IOS,IOEND ; DID WE HIT EOF?
IORI IOS,IODEND ; YES, SET EOF BIT
TRNE IOS,TMO ; TIMED OUT?
IORI IOS,IODERR ; NEED TO SET ERROR BIT FOR UUOCON.
MOVEM IOS,DEVIOS(DDB)
POPJ P,
; DUMP MODE INPUT
DMPI: PUSHJ P,DMPCMD ; FETCH AND CHECK NEXT IOWD FROM COMMAND LIST
POPJ P, ; END OF COMMAND LIST
MOVN TAC,TAC ; TAC←POSITIVE WC.
TLZE TAC1,-1 ; MAKE SURE THIS ISN'T WRITE PROTECTED
JRST UADRER ; ADDRESS ERROR - CAN'T INPUT TO WRITE PROT AREA
DMPIT: PUSHJ P,INPT ; DO AN INPUT
JRST ENDCHK
JUMPG TAC,DMPIT ; IF WE HAVEN'T GOTTEN IT, GO BACK FOR MORE
AOJA UUO,DMPI ; CHECK FOR MORE COMMANDS
;INPT INPT01 INPT11 INPT12 INPT02 INPT17 INPT18 INPT19 INPT21 INPT09 INP09A INPT13 INPT14
;Common input routine. Enter with user address in TAC1 and desired word count
;in TAC. Returns count of words transferred in RH(DAT) and LH of byte ptr to
;last byte transferred in LH(DAT). Returns +1 if error or no data available,
;+2 on some data transferred.
INPT: PUSHJ P,UUOIOK ; MAKE SURE HOST ALIVE AND ALL
POPJ P, ; HOST DEAD
;Read data out of input list and into user core. Some of this code similar to
;INPT in IMPSER.MAC, though cleaned up a bit. Labels have been kept the same
;when possible, for easy reference.
PUSHACS ;Get into TOPS-10 mode
SETT10
SETAC(P1,TAC1) ;User address to store data
HRLI P1,441000 ;Make into byte pointer
PRINTX IMP input only writes 8-bit bytes into user core
SETAC(P2,TAC) ;Desired word count
LSH P2,WD2BYT ;Make it a byte count
SETZ P3, ;Words transferred
MOVSI S,ALLWAT!IOBRKF!IO!IOFST
ANDCAM S,IMPIOS(F)
HRRI S,IODATA
ANDCAB S,DEVIOS(F) ;CLEAR FLAGS
TLNN S,IOBEG ;FIRST TIME AROUND?
JRST INPT01 ;NO
SETZM ISHREG(F) ;YES
MOVSI S,IOFST!IOBEG ;FIRST IO FLAG
XORB S,DEVIOS(F)
INPT01: MOVSI S,IDATWT
IORM S,IMPIOS(F)
IORB S,DEVIOS(F) ;SET IO WAIT FLAGS
OFFSCN ; avoid anarchy
PUSHJ P,INBYTC ;CALL CHECK ROUTINE
JRST INPT02 ;DATA!
INPT11: PUSHJ P,TCPICK↑ ;OPEN? (in TCPSER.MAC)
JRST [ PUSHJ P,INPT13 ;No.
SAVAC(IOS,S)
POPACS
POPJ P,] ;Return error to caller.
SKIPE OKFLAG
SKIPE STOPFLG ;IMP OK?
JRST INPT12 ;NO
PUSHJ P,IMPW60 ;WAIT
JRST INPT01 ;TRY FROM TOP
;Here if IMP not OK.
INPT12: ONSCN
SAVAC(IOS,S)
POPACS ;Back to WAITS mode
JRST IMPLUZ
;Here we move data from the input stream into user core.
INPT02: ONSCN
MOVEI P4,0
EXCH P4,IBFPC(F) ;Get coroutine link, if any.
JUMPN P4,INPT17 ;Proceed if already set
MOVEI P4,INBYTE ;Assume text
;Here to get an input byte
INPT17: MOVSI S,IDATWT ;Set wait flag
IORM S,IMPIOS(F)
IORB S,DEVIOS(F)
OFFSCN
JSP P4,(P4) ;Get a byte
JRST INPT19 ;No more
AOS IBFBYT(F) ;Count bytes read
ONSCN
MOVSI S,IOFST ;Clear first data flg
ANDCAB S,DEVIOS(F)
XCTR XW,[IDPB T1,P1] ;Store it
SOJG P2,INPT17 ;Count and loop
;Here when user data area exhausted
INPT18: SKIPLE IBFBC(F) ;Any input left?
HRRZM P4,IBFPC(F) ;Yes, save linkage
OFFSCN ;avoid confusion
PUSHJ P,INBYTC ;Make sure no more
SKIPA
JRST INPT21 ;Empty
MOVEI S,IODATA ;Set data flag
IORB S,DEVIOS(F)
JRST INPT09 ;DONE: tell NCP and free interrupts
;Here when stream exhausted before user data area
INPT19: MOVEI S,IODATA ;Clear input data flag
ANDCAB S,DEVIOS(F)
;Here when input exhausted
INPT21: PUSHJ P,TCPIFN↑ ;Test for closed (in TCPSER.MAC)
JRST [ ;Closed. Interrupts are on.
PUSHJ P,INPT14 ; Tell user about EOF.
JRST INP09A]
;Here when done.
INPT09: PUSHJ P,TCPWUP↑ ;Update window information (in TCPSER.MAC)
ONSCN ;Allow interrupts again
PUSHJ P,IMPWK1↑ ;Clear flags and such (in IMPSER.MAC)
INP09A: SETAC(T1,TAC) ;Number of words user wanted
LSH P2,BYT2WD ;Number of full words not transferred
SUB T1,P2 ;Number of words transferred
HLL T1,P1 ;Left half of byte ptr
SAVAC(DAT,T1) ;Return to caller here
SAVAC(IOS,S) ;Also make sure IOS is right
JRST POPPJ1 ;Indicate success
;Here if socket not open.
INPT13: ONSCN ;interrupts are safe for democracy.
INPT14: MOVSI S,IOEND ;End of file
IORB S,DEVIOS(F)
SKIPN IBFTHS(F) ;Any data in buffers?
TLNN S,IOFST ;No. Was any input?
JRST IMPWK1↑
MOVEI S,IOIMPM ;No. Error
IORB S,DEVIOS(F)
JRST IMPWK1↑
;CLSO CLSI
CLSO: SKIPN IMPUP↑
POPJ P,
PUSHACS ;Get into TOPS-10 mode
SETT10
PUSHJ P,TCPCLS↑ ; tell TCP about the close.
; close does a TCP push.
TLNN F,OUTBFB!OUTPB ;Output buffer set up?
JRST CLSO1 ;No, forget about flushing last buffer
LDB T1,PIOMOD ;What mode are we in?
CAIGE T1,DR ;Dump maybe?
JRST [ POPACS ;No, do last output for buffered mode
PUSHJ P,OUT
PUSHACS]
MOVSI S,IO ;set flag
IORM S,IMPIOS(F)
IORB S,DEVIOS(F)
CLSO1: PUSHJ P,IMPWK1↑ ;clear flags
JRST POPPOJ
; CLOSE INPUT
CLSI: POPJ P,MPUP↑
;IMPW60 IMPWAT CLRAC1 STTIO1
;ROUTINE TO WAIT FOR INTERRUPT ACTIVITY. RETURNS WHEN WOKEN AT
; INTERRUPT LEVEL OR WHEN WAIT TIMES OUT.
; (SET SOME WAIT FLAG IN IMPIOS)
; MOVE T1,[TIMEOUT SECS]
; PUSHJ P,IMPWAT
; RETURN WHEN I/O DONE OR TIMER TIMES OUT (TIMFLG SET)
; WITH INTERRUPTS TURNED BACK ON!
;JJW - This is an adapted version of the TOPS-10 code in IMPSER.MAC. Timeout
;field in DDB is different and ACs have to be dealt with. Times of more than =63
;seconds are reduced to =63. I don't think it ever gets that high anyway. ACs
;are in TOPS-10 mode when this code is called and when it returns.
ENTRY IMPW60,IMPWAT ;For calls from IMPSER.MAC
IMPW60: MOVEI T1,=60 ;60 SECOND SLEEP
IMPWAT: CAILE T1,77 ;More than maximum?
MOVEI T1,77 ;Yes, set to max (=63 sec)
DPB T1,PDVTIM
ONSCN ;TURN ON INTERRUPTS
MOVEI T3,TIMFLG ;CLEAR TIMEOUT FLAG
ANDCAM T3,IMPIOS(F)
IFN IOS-S,<PUSH P,IOS> ;SETACT uses IOS and TAC, so save these
IFN TAC-T1,<PUSH P,TAC> ; if necessary
MOVE IOS,DEVIOS(F) ;PICK UP I/O STATUS WORD
PUSHJ P,SETACT ;SET IOACT
IFN TAC-T1,<POP P,TAC> ;Restore ACs
IFN IOS-S,<POP P,IOS>
MOVSI T4,ALLWAT ;TEST ALL WAIT FLAGS
TDNN T4,IMPIOS(F) ;WAIT FLAG(S) STILL SET?
JRST IMPWK1↑ ;No, clear flags and return
IFN DDB-F,<SAVAC(DDB,F)>
POPACS ;WAITS mode for WSYNC
PUSHJ P,WSYNC ;YES, WAIT
PUSHACS ;Back to TOPS-10 mode
SETT10
MOVEI T3,TIMFLG
MOVSI T4,ALLWAT
TDNE T4,IMPIOS(F) ;WAIT FLAG STILL SET?
IORM T3,IMPIOS(F) ;YES, SET TIMEOUT FLAG
JRST IMPWK1↑ ;ENSURE FLAGS ARE CLEAR AND RETURN
;Here from TOPS-10 code to execute CLRACT. S has already been set up.
;Saves IOS and TAC if necessary since these are the only ACs used by CLRACT.
CLRAC1:
IFN IOS-S,<PUSH P,IOS
MOVE IOS,S>
IFN TAC-T1,<PUSH P,TAC>
PUSHJ P,CLRACT
IFN TAC-T1,<POP P,TAC>
IFN IOS-S<POP P,IOS>
POPJ P,
;Here from TOPS-10 code to execure STTIOD.
STTIO1: PUSHACS ;J stays set up right.
SETT10
PUSHJ P,STIIOD
POPACS
POPJ P,
;DIE
;Here from TOPS-10 errors that want the system to stop.
DIE: PUSHACS
PUSHJ P,DISUSR
SIXBIT/NET/
PUSHJ P,DISMES
ASCIZ/IMPBUG (/
HRLZ TAC1,P-17(P) ;Get error mnemonic stored in code
PUSHJ P,DISSIX
PUSHJ P,DISMES
ASCIZ/) called from /
MOVE TAC,P-17(P)
SOS TAC ;Back up to the call to DIE
PUSHJ P,DISLOC
PUSHJ P,DISCRLF
PUSHJ P,DISFLUSH
POPACS
PUSHJ P,DDTCALL
JRST CPOPJ1 ;Try to continue
;UUOOOK UUOOK1 ISETEB UUOIOK
;ROUTINE TO BLESS UUO LEVEL I/O BASED ON HOST STATUS.
UUOOOK: PUSHACS ;Get into TOPS-10 mode
SETT10
MOVEI P1,TCPOCK↑ ;Routine to call
UUOOK1: SKIPN IMPUP↑
JRST ISETEB ;Host dead
PUSHJ P,(P1) ;Is connection in legal state?
JRST ISETEB
JRST POPPJ1
ISETEB: POPACS ;Back to WAITS mode
MOVEI IOS,IOIMPM ; SET ERROR BIT SO GET OUT OF UUOCON
IORB IOS,DEVIOS(DDB)
POPJ P,
UUOIOK: PUSHACS ;Get into TOPS-10 mode
SETT10
MOVEI P1,TCPICK↑
JRST UUOOK1
>;IFN IMPNUM